import os, shutil, json

from typing import List
from rich import print as prt

from mido import MidiFile
from MineMusicVisualizer.main import (
    gen_dropping_into_piano,
    DirectionCoordinate,
    gen_colour_map,
    DirectionPointing,
)
from Musicreater import MusicSequence, MineCommand
from Musicreater.plugin import (
    commands_to_structure,
    COMPABILITY_VERSION_121,
    behavior_mcpack_manifest,
    compress_zipfile,
)


file_path = r"C:\Eilles\程设\音创\#master\遠い空へ.mid"
dist_path = "./result"

msq = MusicSequence.from_mido(MidiFile(file_path, clip=True), "遥远的天空")

colourmap = gen_colour_map(list(msq.note_count_per_instrument.keys()))

prt(colourmap)

piano_cmd, drop_cmd_list = gen_dropping_into_piano(
    msq,
    colour_map=colourmap,
    centre_point=DirectionCoordinate(0, 0, 0),
    drop_direction=DirectionPointing("Z", 1),
    expand_direction=DirectionPointing("X", 1),
    upinto_direction=DirectionPointing("Y", 1),
    drop_distance=50,
    blackkey_length=5,
    whitekey_length=9,
)


piano_struct, size, final_pos = commands_to_structure(
    piano_cmd,
    max_height=32,
    compability_version_=COMPABILITY_VERSION_121,
)


if not os.path.exists(dist_path):
    os.makedirs(dist_path)

# 当文件f夹{self.outputPath}/temp/存在时清空其下所有项目，然后创建
if os.path.exists(f"{dist_path}/temp/"):
    shutil.rmtree(f"{dist_path}/temp/")
os.makedirs(f"{dist_path}/temp/functions/")
os.makedirs(f"{dist_path}/temp/structures/")


# 写入manifest.json
with open(f"{dist_path}/temp/manifest.json", "w", encoding="utf-8") as f:
    json.dump(
        behavior_mcpack_manifest(
            pack_description=f"{msq.music_name} 音乐展示包，钢琴瀑布流 - 由 音·预 生成",
            pack_name=msq.music_name + "展示",
            modules_description=f"无 - 由 音·预 生成",
            format_version=2,
            pack_engine_version=[1, 21, 71],
        ),
        fp=f,
        indent=4,
        ensure_ascii=False,
    )


with open(
    os.path.abspath(
        os.path.join(
            dist_path,
            "temp/structures/const-piano.mcstructure",
        )
    ),
    "wb",
) as f:
    piano_struct.dump(f)

prt("钢琴构建部分：", "结构大小", size, "末点坐标", final_pos)

play_drop_list: List[MineCommand] = []

for i in range(len(drop_cmd_list)):

    with open(
        f"{dist_path}/temp/functions/droptick-{i}.mcfunction",
        "w",
        encoding="utf-8",
    ) as f:
        f.write("\n".join([single_cmd.cmd for single_cmd in drop_cmd_list[i]]))
    play_drop_list.append(
        MineCommand(
            command=f"function droptick-{i}",
            tick_delay=1,
            annotation=f"播放第 {i} 帧的瀑布流",
        )
    )

play_struct, size, final_pos = commands_to_structure(
    play_drop_list,
    max_height=32,
    compability_version_=COMPABILITY_VERSION_121,
)

with open(
    os.path.abspath(
        os.path.join(
            dist_path,
            "temp/structures/const-play.mcstructure",
        )
    ),
    "wb",
) as f:
    play_struct.dump(f)


if os.path.exists(f"{dist_path}/{msq.music_name}.mcpack"):
    os.remove(f"{dist_path}/{msq.music_name}.mcpack")

compress_zipfile(
    f"{dist_path}/temp/",
    f"{dist_path}/{msq.music_name}[PIANO].mcpack",
)

shutil.rmtree(f"{dist_path}/temp/")


prt("下落音符部分：", "结构大小", size, "末点坐标", final_pos)

prt("请使用 const-piano 结构构件钢琴，使用 const-play 构建瀑布流播放器")
